function parseCss(value) {
	var n = (typeof(value) === 'string') ? parseFloat(value) : value,
	unit = (typeof(value) === 'string') ? value.replace(n, '') : '';
	return { value: n, unit: unit};
}
var jCss ={
		css: function(opt, value){
				r = this;
				if(!value){
					if(typeof(opt) == "object"){
						for(o in opt){
							if(o == "opacity"){
								this.style["filter"] = "alpha(opacity=" + (opt[o] * 100) + ")"; //IE, as usual
							}

							this.style[o] = opt[o];
						}
					} else {
						switch(opt){
							case "opacity":
								r = this.gO();
							break;
							/*case "top":
								r = this.gT();
							break;
							case "left":
								r = this.gL();
							break;*/
							case "height":
								if(parseCss(this.getCss(opt)).value > 0){
									r = this.getCss(opt);
								} else {
									r = this.gH();
								}
							break;
							case "width":
								if(parseCss(this.getCss(opt)).value > 0){
									r = this.getCss(opt);
								} else {
									r = this.gW();
								}
							break;
							default:
								r = this.getCss(opt);
							break;
						}
					}
				} else {
					if(opt == "opacity"){
						this.style["filter"] = "alpha(opacity=" + (value * 100) + ")"; //IE, as usual
					}
					try {
						if(/[+-\/\*]=/g.test(value)){
							v = value.split('=');
							u = parseCss(v[1]).unit;
							v[1] = isNaN(parseFloat(parseCss(v[1]).value)) ? 0 : parseCss(v[1]).value;
							a = isNaN(parseFloat(parseCss(this.$$(opt)).value)) ? 0 : parseCss(this.$$(opt)).value;
							switch(v[0]){
								case '+':
									this.style[opt] = (a + v[1]) + u;
								break;
								case '-':
									this.style[opt] = (a - v[1]) + u;
								break;
								case '*':
									this.style[opt] = (a * v[1]) + u;
								break;
								case '/':
									this.style[opt] = (a / v[1]) + u;
								break;
							}
						} else {
							this.style[opt] = value;
						}
					}
					catch(e){}
					r = this;
				}
				return r;
			},

		getCss: function(opt){
					return this.style[opt] || this.computed$$(opt);
				},
		computed$$: function(opt){
						//taked from the amazing jQuery source
						var computedStyle;
						elem = this;
						name = opt;
						if ( document.documentElement.currentStyle ) {
							var left,
								ret = elem.currentStyle && elem.currentStyle[ name ],
								rsLeft = elem.runtimeStyle && elem.runtimeStyle[ name ],
								style = elem.style;
							// From the awesome hack by Dean Edwards
							// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
					
							// If we're not dealing with a regular pixel number
							// but a number that has a weird ending, we need to convert it to pixels
							if ( !/^-?\d+(?:px)?$/i.test( ret ) && /^-?\d/.test( ret ) ) {
								// Remember the original values
								left = style.left;
					
								// Put in the new values to get a computed value out
								if ( rsLeft ) {
									elem.runtimeStyle.left = elem.currentStyle.left;
								}
								style.left = name === "fontSize" ? "1em" : (ret || 0);
								ret = style.pixelLeft + "px";
					
								// Revert the changed values
								style.left = left;
								if ( rsLeft ) {
									elem.runtimeStyle.left = rsLeft;
								}
							}
							return ret === "" ? "auto" : ret;
						}
						else {
							computedStyle = document.defaultView.getComputedStyle(elem, null);
						}
						return computedStyle[opt];
				},
		numCss: function(opt){
					r = this.getCss(opt);
					return !r || r === "auto" ? 0 : r;
				},

		getLeft: function(){
					return this.getOffset().left;
				 },

		getTop: function(){
					return this.getOffset().top;
				 },

		getHeight: function(){
						val = this.offsetHeight;
						val -= parseFloat(this.$$("paddingTop")) + parseFloat(this.$$("paddingBottom")) || 0;
						return Math.max(0, Math.round(val));
					},

		getWidth: function(){
						val = this.offsetWidth;
						val -= parseFloat(this.$$("paddingLeft")) + parseFloat(this.$$("paddingRight")) || 0;
						return Math.max(0, Math.round(val));
					},
		getOpacity: function(){
						var r = 1.0;
						if(document.all){ // IE, as usual
							o = this.getCss("filter").toLowerCase() || "";
							if(o.indexOf("opacity=") > -1) r = (parseFloat(/opacity=([^)]*)/.exec(o)[1])/100);
						} else {
							if(this.getCss("opacity") !== "") r = this.getCss("opacity");
						}
						return r;
					},
		getOffset: function(){
				var elem = this;
				var offsetParent = elem.offsetParent,
				prevOffsetParent = elem,
				doc = elem.ownerDocument,
				computedStyle,
				docElem = doc.documentElement,
				body = doc.body,
				defaultView = doc.defaultView,
				prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,
				top = elem.offsetTop,
				left = elem.offsetLeft;
	
				while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
					computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;
					top  -= elem.scrollTop;
					left -= elem.scrollLeft;
		
					if ( elem === offsetParent ) {
						top  += elem.offsetTop;
						left += elem.offsetLeft;
		
						if (/^t(able|d|h)$/i.test(elem.nodeName) ) {
							top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
							left += parseFloat( computedStyle.borderLeftWidth ) || 0;
						}
		
						prevOffsetParent = offsetParent, offsetParent = elem.offsetParent;
					}
		
					prevComputedStyle = computedStyle;
				}
		
				if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) {
					top  += body.offsetTop;
					left += body.offsetLeft;
				}
		
				if (prevComputedStyle.position === "fixed" ) {
					top  += Math.max( docElem.scrollTop, body.scrollTop );
					left += Math.max( docElem.scrollLeft, body.scrollLeft );
				}
		
				return { top: top, left: left };
			},
	hasClass: function(cl){
				return (this.className.indexOf(cl) > -1 ? true : false);
			  },
	addClass: function(cl){
			     if (!this.getAttribute) return false;
			     if(this.hasClass(cl)) return this;
			     var classes = this.getAttribute('class');
			     if(classes==null){
					 this.setAttribute('class',cl);
				 } else {
					 this.setAttribute('class',classes+" "+cl);
				 }

				return this;
			  },
	removeClass: function(cl){
				     if (!this.getAttribute) return false;
				     var classes = this.getAttribute('class');
				     if(classes==null) return this;
				     var arrClasses=classes.split(" ");
				     for(var i=0;i<arrClasses.length;i++){
							if(arrClasses[i]==cl){
						        arrClasses.splice(i,1);
						        break;
    					  }
				     }
				     this.setAttribute('class',arrClasses.join(" "));
				     return this;
				  }
}

	var jColors = {
				d2h: function(dec) { 
						   return dec.toString(16);
					},

				h2d: function(hex) { 
						   return parseInt(hex,16);
					},
				rgb2h: function(r,g,b) { 
						 return [jColors.d2h(r), jColors.d2h(g), jColors.d2h(b)];
				},
				h2rgb: function(h,e,x) {
						return [jColors.h2d(h), jColors.h2d(e), jColors.h2d(x)];
				},
				cssColor2rgb: function(color) {
					 if(color.indexOf('rgb')<=-1) {
						 return jColors.h2rgb(color.substring(1,3),color.substring(3,5),color.substring(5,7));
					 }
					 return color.substring(4,color.length-1).split(',');
				}
	}

jarvis.$$ = jCss.css;
jarvis.gH = jCss.getHeight;
jarvis.gW = jCss.getWidth;
jarvis.gT = jCss.getTop;
jarvis.gL = jCss.getLeft;
jarvis.gO = jCss.getOpacity;
jarvis.extend(jCss);